// 用于定义常用值和引用数据类型、事件和事件处理程序、接口、特性和处理异常的基础类和基类
using System;
// Linq表达式
using System.Linq;
// 提供简化编写并发和异步代码的工作的类型
using System.Threading.Tasks;
// 用于定义泛型集合的接口和类，可允许用户创建强类型集合
using System.Collections.Generic;
// 用于定义微软旗下跨平台实体框架
using Microsoft.EntityFrameworkCore;
// 该项目下的Entity
using MyApi.Entity;
// 该项目下的Data
using MyApi.Db;

namespace MyApi.Repository
{
    public class EfRepository<T> : IRepository<T> where T : BaseEntity
    {
        // 数据库上下文的变量，直接初始化一个数据库上下文的实例对象
        private MyApiDb _db;
        // 构造函数
        public EfRepository(MyApiDb db)
        {
            _db = db;
        }

        // 一个字段成员，用于内部Entity属性（DbSet 表示上下文中给定类型的所有实体的集合或可从数据库中查询的给定类型的所有实体的集合）
        private DbSet<T> _entity;

        // 一个访问受限制的属性，只有访问器，总是返回一个代表T类型的表对象
        protected DbSet<T> Entity
        {
            get
            {
                // 如果_entity为空，说明没有指向一个对象，则从数据库上下文重新获得一个
                if (_entity == null)
                {
                    _entity = _db.Set<T>();
                }
                return _entity;
            }
        }

        // 代表一个可以用于查询T类型的表
        public IQueryable<T> Table
        {
            get
            {
                return Entity.AsQueryable<T>();
            }
        }

        // 删除
        public void Delete(int id)
        {
            var t = Entity.Where(x => x.Id == id).FirstOrDefault();
            Entity.Remove(t);
            _db.SaveChanges();
        }

        // 通过Id进行查找指定实体
        public T GetById(int id)
        {
            var t = Entity.Where(x => x.Id == id).FirstOrDefault();
            return t;
        }

        // 插入
        public void Insert(T entity)
        {
            if (entity == null)
            {
                throw new System.NullReferenceException();
            }

            entity.IsActived = true;
            entity.IsDeleted = false;
            entity.CreatedTime = DateTime.Now;
            entity.UpdatedTime = DateTime.Now;
            entity.DisplayOrder = 0;

            Entity.Add(entity);
            _db.SaveChanges();
        }

        // 插入（异步）
        public async Task InsertAsync(T entity)
        {
            if (entity == null)
            {
                throw new System.NullReferenceException();
            }

            entity.IsActived = true;
            entity.IsDeleted = false;
            entity.CreatedTime = DateTime.Now;
            entity.UpdatedTime = DateTime.Now;
            entity.DisplayOrder = 0;

            await Entity.AddAsync(entity);
            await _db.SaveChangesAsync();
        }

        // 批量插入
        public void InsertBulk(IEnumerable<T> entities)
        {
            foreach (var entity in entities)
            {
                entity.IsActived = true;
                entity.IsDeleted = false;
                entity.CreatedTime = DateTime.Now;
                entity.UpdatedTime = DateTime.Now;
                entity.DisplayOrder = 0;
            }
            Entity.AddRange(entities);
            _db.SaveChanges();
        }

        // 批量插入（异步）
        public async Task InsertBulkAsync(IEnumerable<T> entities)
        {
            foreach (var entity in entities)
            {
                entity.IsActived = true;
                entity.IsDeleted = false;
                entity.CreatedTime = DateTime.Now;
                entity.UpdatedTime = DateTime.Now;
                entity.DisplayOrder = 0;
            }
            await Entity.AddRangeAsync(entities);
            await _db.SaveChangesAsync();
        }

        // 更新
        public void Update(T entity)
        {
            if (entity == null)
            {
                throw new System.NullReferenceException();
            }

            entity.UpdatedTime = DateTime.Now;
            _db.SaveChanges();
        }

        // 批量更新
        public void UpdateBulk(IEnumerable<T> entities)
        {
            foreach (var entity in entities)
            {
                entity.UpdatedTime = DateTime.Now;
            }

            _db.SaveChanges();
        }
    }
}